/***************************************************************************
                          utils_net.h  -  description
                             -------------------
    begin                : Thu Dec 20 2001
    copyright            : (C) 2001 by Liming Xie
    email                : liming_xie@yahoo.com
    
    Revised by		: Thomas Chang
    						: : Many revisions
 ***************************************************************************/

#ifndef _UTILS_NET_H_
#define _UTILS_NET_H_

#define		MSEC_PER_SEC		1000
#define		USEC_PER_SEC		1000000

#ifdef __cplusplus
extern "C" {
#endif

#ifdef linux
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
typedef struct sockaddr_in SOCKADDR_IN;
#endif

/* ------------- common socket related input/output ---------- */

extern int sock_connect( const char *host, int port );

/* ipbind can be NULL, for any address to bind */
extern int sock_listen( int port, const char *ipbind, int backlog );
extern int sock_accept( int fd_listen );

/* ensure safe read/write, without EAGAIN/EINTR */

extern int sock_set_timeout( long time_ms );

extern int sock_read(int fd, void* buffer, int buf_size);

extern int sock_write(int fd, const void* buffer, int buf_size);

/* read a line with '\n', and return with '\0' ended */
extern int sock_read_line(int fd, char* buffer, int buf_size);
extern int sock_peek_line(int fd, char* buffer, int buf_size);

/* read EXACT n bytes from socket,
 * return: bytes readed, or -1 when failed */
extern int sock_read_n_bytes(int fd, void* buffer, int n);
extern int sock_write_n_bytes(int fd, void *buffer, int n);

extern int sock_skip_n_bytes(int fd, int n);

extern int sock_is_connected( int fd );

extern int sock_udp_bind( int port );
extern int sock_udp_broadcast( int fd, int enable );	// enable: 1 yes, 0 no
// create a UDP socket, send messgae then close it. ip==NULL is broadcasting
extern int sock_udp_send( const char *ip, int port, const void* msg, int len );
extern int sock_udp_send0( int fd, SOCKADDR_IN *paddr, int port, const void *msg, int len );
// receive a udp packet, fd should be bind to specific port. saIn is sender's net address.
extern int sock_udp_recv( int fd, void *buf, int size, SOCKADDR_IN *saIn );

// tout in msec
//  -1 means wait until data is ready.
//   0 means no wait at all. Just poll the status
extern int sock_dataready( int fd, int tout );
extern int sock_iqueue(int fd);
extern int sock_oqueue(int fd);

// clean all input data in socket.
// return: number of bytes eaten.
extern int sock_drain( int fd );

/* get host IP address -- first non-loop (127.0.0.1) bound IP */
/* hostname: NULL for local host. Otherwise, the target host name
 *      buf: Output buffer of IP dot number string.
 * return:
 *      packed IP address
 */
extern unsigned long get_host_ip( const char *hostname, char *buf );
/* 
 * in following functions
 * if ifa_name is NULL, then return address of first adapter (exclude "lo")
 */
extern const char *get_ifadapter_name();
extern unsigned long get_ifadapter_ip( const char *ifa_name, char *buf, SOCKADDR_IN *netmask, SOCKADDR_IN *ip_bcast );
/*
 * ifconfig: config network interface adapter 
 * ifname: name of adapter, NULL mean first non lo interface (usually eth0)
 * ip, netmask, gwip: ip address, netmask and defaut gateway IP. NULL means do not change
 */
extern int ifconfig(const char *ifname, const char *ipaddr, const char *netmask, const char *gwip);
extern int get_netaddr( const char *ifname, SOCKADDR_IN *netaddr );
extern int set_netaddr( const char *ifname, SOCKADDR_IN netaddr );
extern int get_netmask( const char *ifname, SOCKADDR_IN *netmask );
extern int set_netmask( const char *ifname, SOCKADDR_IN netmask );
extern unsigned long get_gatewayaddr( const char *ifname, char *buf );
extern int get_mac_addr( const char *ifname, unsigned char *hwaddr );		// hwaddr: 6 bytes mac addr.
extern int set_mac_addr( const char *ifname, unsigned char *hwaddr );

/* get peer name (usually, IP adddress, unless host name for the ip is given in dns server or
 * 'hosts' file.
 *
 */
extern const char* sock_getpeername( int fd, int *port );

// helper - same as inet_addr. but caller does not have to include many socket header files.
extern unsigned long INET_ATON( const char *ipstr );
extern const char *INET_NTOA( unsigned long ip );

#ifdef __cplusplus
};
#endif

#endif /* _UTILS_NET_H_ */
